﻿using System;
using BSF.Log;
using BSF.Tool;

namespace BSF.Caches
{
    
    /// <summary>
    /// 配置缓存提供操作类(App配置中心系统配置项缓存文件)
    /// 初始化:第一次访问配置时，会开启线程取数据库中的配置
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ConfigCacheProvider<T>
    {
        private ConfigCacheModel<T> configCacheModel = new ConfigCacheModel<T>();
        private System.Threading.Thread thread =null;
        private int sleepTime = 5000;
   
        /// <summary>
        /// 初始化函数
        /// </summary>
        /// <param name="configKey">配置Key值</param>
        /// <param name="refreshMethod">刷新回调函数</param>
        /// <param name="refreshFullMethod">刷新回调函数 使用本地文件数据刷新</param>
        /// <param name="intervalTime">间隔时间 秒</param>
        public ConfigCacheProvider(string configKey, Func<DateTime, T> refreshMethod, Action<T> refreshDataByLocalFile, int intervalTime)
        {
            configCacheModel.ConfigKey = configKey;
            configCacheModel.RefreshMethod = refreshMethod;
            configCacheModel.IntervalTime = intervalTime;
            configCacheModel.RefreshDataByLocalFile = refreshDataByLocalFile;
            try
            {
                ReRefresh();
                thread = new System.Threading.Thread(Run);
                thread.Start();
            }
            catch (Exception exp)
            {
                ErrorLog.Write("ConfigCacheProvider-开启" + configKey + "缓存失败:", exp);
            }

        }

        /// <summary>
        /// 刷新数据  调用注册的刷新回调函数
        /// </summary>
        public void ReRefresh()
        {
            configCacheModel.RefreshMethod.Invoke(configCacheModel.LastRefreshTime);
        }

        private void Run()
        {
            try
            {
                while (true)
                {
                    try
                    {
                        T data = default(T);
                        if (configCacheModel == null || ((DateTime.Now - configCacheModel.LastRefreshTime) < TimeSpan.FromSeconds(configCacheModel.IntervalTime)))
                        {
                            System.Threading.Thread.Sleep(sleepTime);
                            continue;
                        }
                        //缓存文件路径
                        string filepath = System.AppDomain.CurrentDomain.BaseDirectory.TrimEnd('\\') + "\\" + "CacheFile\\" + configCacheModel.ConfigKey + ".config";
                        if (configCacheModel != null && configCacheModel.RefreshMethod != null)
                        {
                            try
                            {
                                data = configCacheModel.RefreshMethod.Invoke(configCacheModel.LastRefreshTime);
                                configCacheModel.LastRefreshTime = DateTime.Now;
                            }
                            catch (System.Threading.ThreadAbortException)//过滤线程终止
                            { }
                            catch (Exception exp)
                            {
                                System.Diagnostics.Debug.WriteLine("更新" + configCacheModel.ConfigKey + "缓存失败:" + exp.Message);
                            }
                        }

                        if (data != null)
                        {
                            //根据回调结果更新缓存
                            IOHelper.CreateDirectory(filepath);
                            Serialization.XmlProvider<T> xml = new Serialization.XmlProvider<T>();
                            string strxml = xml.Serializer(data);
                            System.IO.File.WriteAllText(filepath, strxml);
                        }
                        else
                        {
                            //使用缓存文件更新缓存
                            if (System.IO.File.Exists(filepath))
                            {
                                var text = System.IO.File.ReadAllText(filepath);
                                Serialization.XmlProvider<T> xml = new Serialization.XmlProvider<T>();
                                data = xml.Deserialize(text);
                                configCacheModel.RefreshDataByLocalFile(data);
                            }
                        }


                    }
                    catch (System.Threading.ThreadAbortException)//过滤线程终止
                    { }
                    catch (Exception exp)
                    {
                        ErrorLog.Write("ConfigCacheProvider-更新" + configCacheModel.ConfigKey + "缓存:", exp);
                    }
                    System.Threading.Thread.Sleep(sleepTime);
                }
            }
            catch (System.Threading.ThreadAbortException)//过滤线程终止
            { }
            catch (Exception exp)
            {
                ErrorLog.Write("ConfigCacheProvider" + configCacheModel.ConfigKey + "更新缓存:", exp);
            }
        }
         
    }

    /// <summary>
    /// 配置缓存Model
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ConfigCacheModel<T>
    {
        /// <summary>
        /// 配置Key
        /// </summary>
        public string ConfigKey { get; set; }

        /// <summary>
        /// 缓存回调数据刷新函数
        /// </summary>
        public Func<DateTime, T> RefreshMethod { get; set; }

        /// <summary>
        /// 缓存回调函数 本地文件
        /// </summary>
        public Action<T> RefreshDataByLocalFile { get; set; }
        /// <summary>
        /// 间隔时间 秒为单位,（系统自身刷新频率为5秒，故可能有5秒延迟）
        /// </summary>
        public int IntervalTime { get; set; }

        /// <summary>
        /// 上一次缓存刷新时间
        /// </summary>
        public DateTime LastRefreshTime { get; set; }

    }

}
